/**
 * JVM Basics Examples
 * This class demonstrates fundamental concepts of JVM including:
 * - Memory model
 * - Garbage collection
 * - JVM tuning parameters
 */
public class JVMBasics {
    
    // Simulating object creation for garbage collection demonstration
    static class SampleObject {
        private byte[] data = new byte[1024]; // 1KB of data
        private String id;
        
        public SampleObject(String id) {
            this.id = id;
        }
        
        @Override
        public String toString() {
            return "SampleObject{id='" + id + "'}";
        }
    }
    
    public static void main(String[] args) {
        JVMBasics example = new JVMBasics();
        
        // Demonstrating JVM memory model concepts
        example.demonstrateMemoryModel();
        
        // Demonstrating garbage collection concepts
        example.demonstrateGarbageCollection();
        
        // Demonstrating JVM parameter usage
        example.explainJVMParameters();
    }
    
    /**
     * Method to demonstrate JVM memory model concepts
     */
    public void demonstrateMemoryModel() {
        System.out.println("=== JVM Memory Model ===");
        System.out.println("JVM memory is divided into several areas:");
        System.out.println("1. Method Area - Stores class metadata, constant pool, static variables");
        System.out.println("2. Heap - Stores object instances and arrays (shared by all threads)");
        System.out.println("3. JVM Stack - Stores local variables and partial results for each thread");
        System.out.println("4. PC Register - Stores the address of the current instruction for each thread");
        System.out.println("5. Native Method Stack - Used for native methods (C/C++)");
        System.out.println();
        
        // Show heap memory information
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        
        System.out.println("Heap Memory Information:");
        System.out.println("Max memory: " + maxMemory / (1024 * 1024) + " MB");
        System.out.println("Total memory: " + totalMemory / (1024 * 1024) + " MB");
        System.out.println("Free memory: " + freeMemory / (1024 * 1024) + " MB");
        System.out.println("Used memory: " + usedMemory / (1024 * 1024) + " MB");
        System.out.println();
    }
    
    /**
     * Method to demonstrate garbage collection concepts
     */
    public void demonstrateGarbageCollection() {
        System.out.println("=== Garbage Collection ===");
        System.out.println("Garbage Collection is an automatic memory management feature in JVM.");
        System.out.println("It reclaims memory occupied by objects that are no longer reachable.");
        System.out.println();
        
        System.out.println("Types of Garbage Collectors:");
        System.out.println("1. Serial GC - Single-threaded, suitable for small applications");
        System.out.println("2. Parallel GC - Multi-threaded, focuses on throughput");
        System.out.println("3. G1 GC - Garbage-First, balances throughput and latency");
        System.out.println("4. ZGC - Low-latency garbage collector (JDK 11+)");
        System.out.println("5. Shenandoah GC - Low-pause concurrent garbage collector");
        System.out.println();
        
        // Demonstrate object creation and garbage collection
        System.out.println("Creating objects to demonstrate GC...");
        for (int i = 0; i < 10000; i++) {
            SampleObject obj = new SampleObject("Object" + i);
            // These objects become eligible for GC after this loop
        }
        
        System.out.println("Objects created. Calling garbage collector...");
        System.gc(); // Suggest JVM to run garbage collection
        
        // Show memory status after GC
        Runtime runtime = Runtime.getRuntime();
        long usedMemory = runtime.totalMemory() - runtime.freeMemory();
        System.out.println("Memory used after GC suggestion: " + usedMemory / (1024 * 1024) + " MB");
        System.out.println();
    }
    
    /**
     * Method to explain JVM parameters
     */
    public void explainJVMParameters() {
        System.out.println("=== JVM Tuning Parameters ===");
        System.out.println("Common JVM parameters for performance tuning:");
        System.out.println();
        
        System.out.println("Memory Settings:");
        System.out.println("-Xms<size>     - Initial heap size");
        System.out.println("-Xmx<size>     - Maximum heap size");
        System.out.println("-Xmn<size>     - Size of young generation");
        System.out.println("-XX:MetaspaceSize=<size> - Initial metaspace size");
        System.out.println();
        
        System.out.println("Garbage Collection Settings:");
        System.out.println("-XX:+UseSerialGC         - Use Serial Garbage Collector");
        System.out.println("-XX:+UseParallelGC       - Use Parallel Garbage Collector");
        System.out.println("-XX:+UseG1GC             - Use G1 Garbage Collector");
        System.out.println("-XX:+UseZGC              - Use Z Garbage Collector (JDK 11+)");
        System.out.println("-XX:+UseShenandoahGC     - Use Shenandoah Garbage Collector");
        System.out.println();
        
        System.out.println("Monitoring and Logging:");
        System.out.println("-XX:+PrintGC             - Print basic GC information");
        System.out.println("-XX:+PrintGCDetails      - Print detailed GC information");
        System.out.println("-Xloggc:<file>           - Log GC information to file");
        System.out.println("-XX:+HeapDumpOnOutOfMemoryError - Generate heap dump on OOM");
        System.out.println();
        
        System.out.println("Performance Tuning:");
        System.out.println("-XX:MaxGCPauseMillis=<ms> - Target maximum GC pause time");
        System.out.println("-XX:GCTimeRatio=<ratio>   - Target ratio of GC time to application time");
        System.out.println("-XX:+UseStringDeduplication - Enable string deduplication (G1 only)");
        System.out.println();
        
        // Show current JVM parameters
        System.out.println("Current JVM Information:");
        System.out.println("Java Version: " + System.getProperty("java.version"));
        System.out.println("Java Vendor: " + System.getProperty("java.vendor"));
        System.out.println("JVM Name: " + System.getProperty("java.vm.name"));
        System.out.println("JVM Version: " + System.getProperty("java.vm.version"));
        System.out.println();
    }
}